HwEnc Calculations


In [1]:
# Function to calculate the Bits needed for a given number
def unsigned_num_bits(num):
  _nbits = 1
  _n = num
  while(_n > 1):
    _nbits = _nbits + 1
    _n     = _n / 2
  return _nbits

Pixel & SubPixel Calculations

$ pixel_{Pitch}=\frac{25400\frac{\mu m}{inch}}{{Resolution}} $

$ sub\_pixel_{Pitch}=\frac{25400\frac{\mu m}{inch}}{{Resolution*NbrOfSubpixels}} $


In [24]:
import numpy as np
resolutions    = [150, 360, 600, 1200, 2400, 4800] # dpi
inch2cm        = 2.54 # cm/inch
nbrOfSubpixels = 32

len(resolutions)
# Calulation Pixel Pinch
pixel_pitch = np.empty(shape=[ len(resolutions) ], dtype=np.float64) # um
for i in range(len(resolutions)):
  pixel_pitch[i] = (inch2cm/resolutions[i])*10000

# Calculation Subpixel Pinch
sub_pixel_pitch = np.empty(shape=[len(resolutions)], dtype=np.float64) # um
for i in range(len(resolutions)):
  sub_pixel_pitch[i] = pixel_pitch[i]/nbrOfSubpixels
  
  
for i in range(len(resolutions)):
  print("Resolution: {:>10.5f} dpi   Pixel Pitch: {:>10.5f} um   Sub Pixel Pitch: {:>7.5f} um".format(resolutions[i], pixel_pitch[i], sub_pixel_pitch[i]))


Resolution:  150.00000 dpi   Pixel Pitch:  169.33333 um   Sub Pixel Pitch: 5.29167 um
Resolution:  360.00000 dpi   Pixel Pitch:   70.55556 um   Sub Pixel Pitch: 2.20486 um
Resolution:  600.00000 dpi   Pixel Pitch:   42.33333 um   Sub Pixel Pitch: 1.32292 um
Resolution: 1200.00000 dpi   Pixel Pitch:   21.16667 um   Sub Pixel Pitch: 0.66146 um
Resolution: 2400.00000 dpi   Pixel Pitch:   10.58333 um   Sub Pixel Pitch: 0.33073 um
Resolution: 4800.00000 dpi   Pixel Pitch:    5.29167 um   Sub Pixel Pitch: 0.16536 um

Resolution Gain Calculations

$Resolution_{Gain} = 2^{16}\frac{Encoder_{Resolution}}{Input_{Resolution}}$


In [26]:
import numpy as np
encoder_resolution = 2 # um
input_resolution   = sub_pixel_pitch

gain = np.empty(shape=[len(resolutions)], dtype=np.float64)
for i in range(len(resolutions)):
  gain[i] = 2**16 * (encoder_resolution/input_resolution[i])

for i in range(len(resolutions)):
  print("Resolution: {:4} dpi   Resolution Gain: {:>12.5f} or 0x{:08X} needs {} Bits".format(resolutions[i],gain[i],int(gain[i]),unsigned_num_bits(int(gain[i]))))


Resolution:  150 dpi   Resolution Gain:  24769.51181 or 0x000060C1 needs 16 Bits
Resolution:  360 dpi   Resolution Gain:  59446.82835 or 0x0000E836 needs 17 Bits
Resolution:  600 dpi   Resolution Gain:  99078.04724 or 0x00018306 needs 18 Bits
Resolution: 1200 dpi   Resolution Gain: 198156.09449 or 0x0003060C needs 19 Bits
Resolution: 2400 dpi   Resolution Gain: 396312.18898 or 0x00060C18 needs 20 Bits
Resolution: 4800 dpi   Resolution Gain: 792624.37795 or 0x000C1830 needs 21 Bits

HW Encoder divider calculation


In [6]:
# Settings
encoder_resolution = 6    # external encoder resolution [um p. pulse] 
input_resolution   = 32   # resolution wanted for interpolator [sub pixel] 
print_resolution   = 600  # print resolution [dpi]
maxResBitNb        = 19   # FPGA limitation for HW Encoder resolution

# Calculations & print
px_dist = (25.4 * 1000 / print_resolution)     # pixel distance [um]
pulse_p_pixel = px_dist / encoder_resolution   # pulse generated between pixel
#print "pixel distance [um]:      {}".format(px_dist)

print("Hardware Encoder Settings")
print("--------------------------")
print("encoder resolution[um]:       {}".format(encoder_resolution))
print("pixel resolution:             {}".format(print_resolution))
print("required pulse per pixel:     {}".format(input_resolution))
print("")
print("pulse per pixel:              {} ( @{:4}dpi )".format(pulse_p_pixel, print_resolution))

HW_Enc_resolution_range = 2**16                                   # full divider range of fpga

HW_Enc_reso_div       = pulse_p_pixel / input_resolution          # divider needed (exact)
HW_Enc_reso_setting_f = HW_Enc_resolution_range / HW_Enc_reso_div # setting for hw encoder resolution (floating number)
HW_Enc_reso_setting   = int(HW_Enc_reso_setting_f)                # setting for hw encoder resolution (divider rounded)

# if (pulse_p_pixel < input_resolution):
# hint = "!!! Encoder resolution is too small !!!"
if unsigned_num_bits(int(HW_Enc_reso_setting)) > maxResBitNb:
  hint = "!!! Hardware Encoder divider has too many bits (max {}bit)".format(maxResBitNb)
else:
  hint = "Encoder resolution is OK"

print("HWEnc resolution range:       {} ( {}bit )".format(HW_Enc_resolution_range, unsigned_num_bits(int(HW_Enc_resolution_range)-1)))
print("Resolution divider:           {} ( e:{},r:{},s:{} )".format(HW_Enc_reso_div, encoder_resolution, print_resolution, input_resolution))
print("HWEnc divider:                {} ( rounded: {} )".format(HW_Enc_reso_setting_f, HW_Enc_reso_setting))
print("")
print("Register value")
print("--------------------------")
print("Enter as HWEnc divder:        0x{:X}".format(HW_Enc_reso_setting) + "    >>> " + hint )


Hardware Encoder Settings
--------------------------
encoder resolution[um]:       6
pixel resolution:             600
required pulse per pixel:     32

pulse per pixel:              7.055555555555556 ( @ 600dpi )
HWEnc resolution range:       65536 ( 17bit )
Resolution divider:           0.22048611111111113 ( e:6,r:600,s:32 )
HWEnc divider:                297234.14173228346 ( rounded: 297234 )

Register value
--------------------------
Enter as HWEnc divder:        0x48912    >>> !!! Hardware Encoder divider has too many bits (max 19bit)

Calculation of .... ask FAF


In [37]:
# Settings
speed = 1 # m/s
print_resolution   = 1200  # print resolution [dpi]
cycle_time = 0.002 # [sec] PLC Cycle Time
fpga_clk = 100E6
interpolator_step = 128

# Calculations & print
px_dist = (25.4 * 1000 / print_resolution)     # pixel distance [um]
subpixel_sec = (speed * 32) /(px_dist * 0.000001)
subpixel_cycle = subpixel_sec * cycle_time

print("pixel distance      : {:>15.5f} [um]".format(px_dist))
print("subpixel speed      : {:>15.5f} [1/s]".format(subpixel_sec))
print("subpixel/cycle      : {:>15.5f} [ - ]".format(subpixel_cycle))

# Calculations in NIOS
period_base_value = fpga_clk/(1/cycle_time) * interpolator_step
output            = period_base_value/subpixel_cycle - interpolator_step
freq              = 1/(32*(output/interpolator_step)*1/fpga_clk)
print("Interpolator Period : {:>15.5f} [ - ]".format(output))
print("Print frequency     : {:>15.5f} [ - ]".format(freq))


pixel distance      :        21.16667 [um]
subpixel speed      :   1511811.02362 [1/s]
subpixel/cycle      :      3023.62205 [ - ]
Interpolator Period :      8338.66667 [ - ]
Print frequency     :     47969.29965 [ - ]

Calculation PLC Encoder Resolution


In [38]:
# Calc Encoder Resolution
def encoder_resolution(pulse_per_rev=0, circumference_wheel_mm=0):
  enc_resolution = (circumference_wheel_mm*1000)/pulse_per_rev

  print("Pulse Per Revelation = {} Pulses".format(pulse_per_rev))
  print("Circumference Wheel  = {} mm = {}um".format(circumference_wheel_mm, circumference_wheel_mm*1000))
  print("Encoder Resolution   = {} um/pulse /4={} um/pulse".format(enc_resolution, enc_resolution/4))
  
#Steinemann
pulse_per_rev = 53718 # Pulses per revelation
circumference_wheel_mm = 282.6 #mm
encoder_resolution(pulse_per_rev, circumference_wheel_mm)


Pulse Per Revelation = 53718 Pulses
Circumference Wheel  = 282.6 mm = 282600.0um
Encoder Resolution   = 5.2608064335976765 um/pulse /4=1.3152016083994191 um/pulse

Calculation PLC Encoder Pulses Settings


In [39]:
# Calc Encoder Pulses Setting
def ppr(enc_resolution=0, circumference_wheel_mm=0):
  pulse_per_rev = (circumference_wheel_mm*1000)/enc_resolution

  print("Encoder Resolution   = {} um/pulse".format(enc_resolution))
  print("Circumference Wheel  = {} mm = {}um".format(circumference_wheel_mm, circumference_wheel_mm*1000))
  print("Pulse Per Revelation = {} Pulses /4={} Pulses".format(pulse_per_rev, pulse_per_rev/4))

enc_resolution = 2.012 # um / pulse
circumference_wheel_mm = 282.6 #mm
ppr(enc_resolution, circumference_wheel_mm)


Encoder Resolution   = 2.012 um/pulse
Circumference Wheel  = 282.6 mm = 282600.0um
Pulse Per Revelation = 140457.2564612326 Pulses /4=35114.31411530815 Pulses

In [40]:
def speed_calc(speed):
  speed_m_s = speed/60.0
  print("Speed => {}m/min = {}m/s".format(speed, speed_m_s))

speed = 2.0 # m/min
speed_calc(speed)

speed = 150.0 # m/min
speed_calc(speed)


Speed => 2.0m/min = 0.03333333333333333m/s
Speed => 150.0m/min = 2.5m/s
$$2^{31}*\frac{0.0254}{600}*\frac{1}{32} = 2840m = 2500\frac{sheets}{90cm} + 25cm(gap)$$

In [42]:
# Constants
dpi            = 600  # dpi
inch2mm        = 25.4 # mm/inch
subpixels      = 32   # subpixels

counterBitNb   = 31   # bit

# Calculation
pixel_pitch = (((inch2mm/1000)/dpi))
counterlength = (2**counterBitNb / subpixels) * pixel_pitch


pixels = counterlength / pixel_pitch
bits_needed = unsigned_num_bits(int(pixels))

print("Pixel Pitch    = {} m".format(pixel_pitch))
print("Pixels         = {} px".format(pixels))
print("Pixels         = 0x{:X} px".format(int(pixels)))
print("Needs          = {} bit".format(bits_needed))
print("Counter length = {} m".format(counterlength))


# Papers
papers    = 2500 # Pcs
gap       = 25   # cm
papersize = 90   # cm

total_length = (papersize+gap)*papers
print("Total Length   = {} m".format(total_length/100))


Pixel Pitch    = 4.233333333333333e-05 m
Pixels         = 67108864.0 px
Pixels         = 0x4000000 px
Needs          = 27 bit
Counter length = 2840.941909333333 m
Total Length   = 2875.0 m